responseを返す前にclient側から切断された場合、graceful shutdown timer内にrequest & response objectが残り続ける
from scrapbox.ioのみ時間経過でメモリ使用量が増加する原因を、Codex CLIとともに探る
graceful shutdownが、responseを返す前に切断したrequestを考慮していないCodex CLI.icon
src/server/lib/graceful-shutdown.js:52-75 では各リクエストごとに setInterval を起動し、res.finished が true になるまで 5 秒おきに監視していますが、クライアント側がレスポンス完了前に接続を切ったケースを考慮していません。
Express/Node では切断時に res.finished は false のままなので、そうしたリクエストごとに setInterval が永遠に走り続け、タイマーと一緒にres / req / クロージャーが GC されずに残り続けます。
時間経過とともに積み上がる点で、リクエスト数より稼働時間に比例して RSS が増える症状と一致します。
対応の方向性
res.once('finish', clear) と res.once('close', clear) を使って必ずクリーンアップする。
もしくは setInterval ではなく単発の setTimeout+on-finished 等で完了/切断時に count を減らす。
これで異常終了したリクエストでもタイマーが解放され、プロセスを再起動しなくてもメモリ使用量が頭打ちになります。
確かにsetIntervalの中のresがメモリリークしてそうだshokai.icon
setIntervalが止まらないと、resへの参照が解放されない
Expressのresは、res.reqにrequest objectへの参照も持っている
これも解放されない
デカいrequest bodyとかもそのまま残り続けるだろう
done.icon responseを返す前にclient側から切断された場合、graceful shutdown timer内にrequest & response objectが残り続ける #7934
30秒後に発火するsetTimeoutで強制タイムアウトフラグを立て、5秒毎のsetIntervalを止めるようにした
done.icon 正常にレスポンスを返せた場合に、30秒後に発火する強制タイムアウトフラグのsetTimeoutを解除し忘れていた #7936